/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package caro.client.controller;

import caro.app.bussiness.UserSession;
import caro.app.bussiness.ClientUtil;
import caro.app.protocolprovider.BusyPro;
import caro.app.protocolprovider.CheckCellPro;
import caro.app.protocolprovider.LeavePro;
import caro.app.protocolprovider.LostPro;
import caro.app.protocolprovider.PlayRequestPro;
import caro.app.protocolprovider.ProtocolProcessing;
import caro.app.protocolprovider.RefuseClientPro;
import caro.app.protocolprovider.StartPro;
import caro.app.protocolprovider.WinPro;
import caro.app.protocolprovider.chat.ChatProtocolProcessing;
import caro.app.protocolprovider.chat.SendMessagePro;
import caro.client.gui.MainInterface;
import caro.client.gui.Messages;
import caro.client.gui.PopupTable;
import java.awt.Color;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JOptionPane;

/**
 *
 * @author NQ
 */
public class MainInterfaceCtrl extends Thread{

    private MainInterface mainView;
    private UserSession session;
    private BoardListener boardListener;
    public MainInterfaceCtrl(MainInterface main){
        this.mainView = main;
        this.mainView.addWindowListener(new WindowsListener());
        this.mainView.addUsersListListener(new ListUsersListener());
        this.mainView.addChatListener(new ChatListener());
        boardListener = new BoardListener();
        this.mainView.addBoardListener(boardListener);
        this.mainView.disableBoard(boardListener);
        this.session = main.getUserSession();
    }
    @Override
    public void run() {
        //Create input and output stream
        try{
            BufferedReader reader = new BufferedReader(new InputStreamReader(mainView.getSocket().getInputStream()));
            PrintWriter writer = new PrintWriter(mainView.getSocket().getOutputStream());
            while(true){

                String line = reader.readLine();
                System.out.println("Message : " + line);
                if(null == line)
                    break;
                String protocol = ProtocolProcessing.getProtocol(line);
                if(ProtocolProcessing.NEW.equals(protocol)){
                    String username = ProtocolProcessing.explainNew(line).username;
                    System.out.println("Username : " + username);
                    mainView.addFree(username);
                }else if(ProtocolProcessing.PLAY_REQUEST.equals(protocol)){
                    PlayRequestPro playRequest = ProtocolProcessing.explainPlayRequest(line);
                    String username = playRequest.username;
                    int answer = JOptionPane.showConfirmDialog(mainView, Messages.getString("playRequest.content", username), Messages.getString("playRequest.title"), JOptionPane.YES_NO_OPTION);
                    if(answer == JOptionPane.NO_OPTION){
                        writer.println(ProtocolProcessing.getRefuse(username));
                        writer.flush();
                    }else{
                        writer.println(ProtocolProcessing.getAccept(username));
                        writer.flush();
                    }
                }else if(ProtocolProcessing.REFUSE.equals(protocol)){
                    RefuseClientPro refuse = ProtocolProcessing.explainRefuse(line);
                    JOptionPane.showMessageDialog(mainView, Messages.getString("refuse.content", refuse.username), Messages.getString("refuse.title"), JOptionPane.OK_OPTION);
                }else if(ProtocolProcessing.START.endsWith(protocol)){
                    mainView.setEnableChatInput();
                    mainView.enableBoard(boardListener);
                    StartPro start = ProtocolProcessing.explainStart(line);
                    session.setCurrentOpponent(start.username);
                    session.setCurrentValue(start.pawnValue);
                    mainView.setSessionInfo(start.username, start.pawnValue);
                }else if(ProtocolProcessing.CHECK.equals(protocol)){
                    CheckCellPro checkPro = ProtocolProcessing.explainCheckCell(line);
                    //mainView.enableBoard(boardListener);
                    mainView.getBoard()[checkPro.row][checkPro.column].setIcon((ImageIcon)ClientUtil.getInstance().getPawnDisplay(checkPro.value));
                    session.check(checkPro.row, checkPro.column, checkPro.value);
                    session.enableAllTable();
                    mainView.setPlaysInfo(mainView.getUserSession().getMyUsername());
                } else if(ProtocolProcessing.BUSY.equals(protocol)){
                    BusyPro busy = ProtocolProcessing.explainBusy(line);
                    mainView.addBusy(busy.username1);
                    mainView.addBusy(busy.username2);
                } else if(ProtocolProcessing.WIN.equals(protocol)){
                    JOptionPane.showMessageDialog(mainView, Messages.getString("win.content", session.getCurrentOpponent()), Messages.getString("win.title"), JOptionPane.OK_OPTION);
                    //Send leave
                    writer.println(ProtocolProcessing.getLeave(session.getMyUsername(), session.getCurrentOpponent()));
                    writer.flush();
                    mainView.removeBusy(session.getCurrentOpponent());
                    mainView.removeBusy(session.getMyUsername());
                    //Now clear all session
                    mainView.clearSession();
                    mainView.clearBoard();
                    mainView.clearUserInfo();
                    mainView.setDisableChatInput();
                    mainView.disableBoard(boardListener);
                    
                }else if(ProtocolProcessing.LOST.equals(protocol)){
                    LostPro lost = ProtocolProcessing.explainLost(line);
                    mainView.getBoard()[calculateRealRow(lost.row, lost.position)]
                            [calculateRealColumn(lost.column, lost.position)].setIcon((ImageIcon)ClientUtil.getInstance().getPawnDisplay(lost.pownValue));
                    JOptionPane.showMessageDialog(mainView, Messages.getString("lost.content", session.getCurrentOpponent()), Messages.getString("lost.title"), JOptionPane.OK_OPTION);
                    mainView.removeBusy(session.getCurrentOpponent());
                    mainView.removeBusy(session.getMyUsername());
                    mainView.clearSession();
                    mainView.clearBoard();
                    mainView.clearUserInfo();
                    mainView.setDisableChatInput();
                    mainView.disableBoard(boardListener);
                }else if(ProtocolProcessing.LEAVE.equals(protocol)){
                    LeavePro leave = ProtocolProcessing.explainLeave(line);
                    if(session.getCurrentOpponent()!= null && (session.getCurrentOpponent().equals(leave.username1) || 
                            session.getCurrentOpponent().equals(leave.username2))){
                        JOptionPane.showMessageDialog(mainView, Messages.getString("leave.content", session.getCurrentOpponent()), Messages.getString("leave.title"), JOptionPane.OK_OPTION);
                        mainView.removeUser(session.getCurrentOpponent());
                        mainView.removeBusy(session.getMyUsername());
                        mainView.clearSession();
                        mainView.clearBoard();
                        mainView.clearUserInfo();
                        mainView.setDisableChatInput();
                        mainView.disableBoard(boardListener);
                    }else{
                        mainView.removeUser(leave.username1);
                        mainView.removeBusy(leave.username2);
                    }
                }else if(ProtocolProcessing.EXIT.equals(protocol)){
                    mainView.removeUser(ProtocolProcessing.explainExit(line).username);
                }else if(ChatProtocolProcessing.SEND_MESSAGE.equals(protocol)){
                    SendMessagePro sendPro = ChatProtocolProcessing.explainSendMessagePro(line);
                    mainView.setTextContent(sendPro.content, sendPro.username);
                }
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    private int calculateRealRow(int virtualRow, char map){
        switch (map){
            case ClientUtil.WIN_ROW:
                return virtualRow;
            case ClientUtil.WIN_COLUMN: case ClientUtil.WIN_C1: case ClientUtil.WIN_C2:
                return virtualRow + ClientUtil.NUM_WIN - 1;
            default:
                return virtualRow;
        }
    }
    private int calculateRealColumn(int virtualColumn, char map){
        switch (map){
            case ClientUtil.WIN_ROW: case ClientUtil.WIN_C1:
                return virtualColumn + ClientUtil.NUM_WIN - 1;
            case ClientUtil.WIN_COLUMN:
                return virtualColumn;
            case ClientUtil.WIN_C2:
                return virtualColumn - ClientUtil.NUM_WIN + 1;
            default:
                return virtualColumn;
        }
    }
    class ListUsersListener extends MouseAdapter{

        @Override
        public void mouseClicked(MouseEvent e) {
            String userName = mainView.getSelectedUser();
            if(!userName.endsWith(MainInterface.BUSY_END_STRING) && !userName.equals(session.getMyUsername())){
                PopupTable popup = new PopupTable(userName);
                PopupTableCtrl popupCtrl = new PopupTableCtrl(mainView.getSocket(), popup);
                popup.show(mainView.getListUser(), e.getX(), e.getY());
            }
        }
    }
    
    class BoardListener extends MouseAdapter{
        @Override
        public void mousePressed(MouseEvent e) {
            JLabel[][] board = mainView.getBoard();
            for(int i = 0; i < MainInterface.R; i++)
                for(int j = 0; j < MainInterface.C; j++){
                    if(((JLabel)e.getSource()).getName().equals(board[i][j].getName())){
                        if(session.getTmpBoard()[i][j] != UserSession.DISABLE && session.getRealBoard()[i][j] != session.getCurrentValue() &&
                                session.getRealBoard()[i][j] != (session.getCurrentValue()+1)%2){
                                PrintWriter writer = null;
                                try {
                                    System.out.println("click");
                                     writer = new PrintWriter(mainView.getSocket().getOutputStream());
                                     writer.println(ProtocolProcessing.getCheckCell(session.getCurrentOpponent(), i, j, session.getCurrentValue()));
                                     writer.flush();
                                     board[i][j].setIcon((ImageIcon)ClientUtil.getInstance().getPawnDisplay(session.getCurrentValue()));
                                     session.check(i, j, session.getCurrentValue());
                                     session.disableAllTable();
                                     mainView.setPlaysInfo(mainView.getUserSession().getCurrentOpponent());
                                     //mainView.disableBoard(boardListener);
                                } catch (IOException ex) {
                                    Logger.getLogger(MainInterfaceCtrl.class.getName()).log(Level.SEVERE, null, ex);
                                }
                        }
                        break;
                    }
                }
        }
    }
    class WindowsListener extends WindowAdapter{

        @Override
        public void windowClosing(WindowEvent e) {
            stopCtrl();
            Socket s = mainView.getSocket();
            if(s.isConnected()){
                try{
                    String userName = session.getCurrentOpponent() == null ? "NULL" : session.getCurrentOpponent();
                    PrintWriter writer = new PrintWriter(s.getOutputStream());
                    writer.println(ProtocolProcessing.getExit(userName));
                    writer.flush();
                    System.exit(0);
                }catch(Exception ex){
                    ex.printStackTrace();
                }
            }
        }
               
    }
    class ChatListener implements KeyListener{

        @Override
        public void keyTyped(KeyEvent e) {
            
        }

        @Override
        public void keyPressed(KeyEvent e) {
            if(e.getKeyCode() == KeyEvent.VK_ENTER){
                mainView.setTextContent(mainView.getChatInput(), session.getMyUsername());
                //Now send message
                try{
                    PrintWriter writer = new PrintWriter(mainView.getSocket().getOutputStream());
                    writer.println(ChatProtocolProcessing.getSendMessagePro(session.getCurrentOpponent(), mainView.getChatInput()));
                    writer.flush();
                    mainView.setChatInput("");
                }catch(Exception ex){
                    ex.printStackTrace();
                }
            }
        }

        @Override
        public void keyReleased(KeyEvent e) {
            
        }
        
    }
    private void stopCtrl(){
        this.interrupt();
        if(!this.isAlive()){
            mainView.dispose();
        }
    }
}
